import requests
from bs4 import BeautifulSoup
import os
import zipfile
import time
import random
import shutil
# pip install fake_useragent
from fake_useragent import UserAgent

class SpiderNongYaoHeroSkinImg():
    def __init__(self):
        self.url = 'https://pvp.qq.com/web201605/herolist.shtml'
        self.headers = {
            'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
            'accept-language': 'zh-CN,zh;q=0.9',
            'referer': 'https://pvp.qq.com/',
            'sec-fetch-dest': 'document',
            'sec-fetch-mode': 'navigate',
            'sec-fetch-site': 'same-origin',
            'sec-fetch-user': '?1',
            'upgrade-insecure-requests': '1',
            'user-agent': UserAgent().chrome
        }
        # 由于农药有一百多个英雄，每个英雄有多个皮肤，下载量太大，所以限制下
        self.hero_num = 20
        # 皮肤图片下载路径
        self.skin_output_path = './images/nongyao/'
        # 压缩文件输出路径
        self.skin_zip_path = './images/nongyao_skin.zip'
    def __main__(self):
        print('王者荣耀英雄皮肤爬虫程序开始执行，请稍后。。。')
        response = requests.get(self.url, self.headers)
        bs = BeautifulSoup(response.content.decode(errors='ignore'), 'lxml')
        hero_elements = bs.select('.zkcontent > div > .herolist-box > .herolist-content > ul > li')
        count = 0
        if len(hero_elements) < self.hero_num:
            self.hero_num = len(hero_elements)
        for hero_element in hero_elements:
            if count >= self.hero_num :
                break
            hero_id = hero_element.select_one('li > a')['href'].split('/')[-1].split('.')[0]

            hero_detail_url = self.url.split('herolist.shtml')[0] + hero_element.select_one('li > a')['href']
            hero_detail_res = requests.get(hero_detail_url)
            hero_detail_bs = BeautifulSoup(hero_detail_res.content, 'html.parser', from_encoding='utf-8')
            hero_name = hero_detail_bs.find('h2', attrs={'class': 'cover-name'}).get_text()
            skin_name_strs = hero_detail_bs.select_one('.con1-pic > div > .pic-pf > ul')['data-imgname']
            skin_name_list = skin_name_strs.split('|')
            for i in range(len(skin_name_list)):
                skin_name_list[i] = skin_name_list[i].split('&')[0].lstrip().rstrip()

            self.__download_skin__(hero_name, hero_id, skin_name_list)
            count = count + 1
            time.sleep(random.randint(3, 5))

        self.__zip_file__()
        shutil.rmtree(self.skin_output_path)
    def __download_skin__(self, hero_name, hero_id, skin_name_list):
        for i in range(len(skin_name_list)):
            image_url = f'https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/{hero_id}/{hero_id}-bigskin-{i+1}.jpg'
            image_name = image_url.split('/')[-1]
            image_name = hero_name + '-' + skin_name_list[i] + '.' + image_name.split('-')[-1].split('.')[-1]
            img_download_path = './images/nongyao/'
            img_download_path_first = './images/'
            self.__create_dir__(img_download_path, img_download_path_first)
            image_res = requests.get(image_url)
            if image_res.status_code==200:
                with open(img_download_path + image_name, 'wb') as file:
                    file.write(image_res.content)
                    file.close()
                print('英雄----{0}----皮肤----{1}----下载完成！'.format(hero_name, skin_name_list[i]))
                time.sleep(random.randint(1, 3))
    def __create_dir__(self, dir, first_dir):
        # 判断该文件夹是否存在
        if os.path.exists(first_dir) is False:
            # 不存在则创建
            os.mkdir(first_dir)
            os.mkdir(dir)
        elif os.path.exists(dir) is False:
            os.mkdir(dir)
    def __zip_file__(self):
        '''压缩文件夹'''
        # 获取倒数第二个/出现的位置
        last_sec_num = self.skin_output_path.rfind('/', 0, self.skin_output_path.rfind('/')-1)
        # skin_output_path的上一级目录
        parent_path = self.skin_output_path[0:last_sec_num+1]
        zip_dir = zipfile.ZipFile(self.skin_zip_path, 'w', zipfile.ZIP_DEFLATED)
        # 多层级压缩
        for root, dirs, files in os.walk(self.skin_output_path):
            for file in files:
                if str(file).startswith("~$"):
                    continue
                filepath = os.path.join(root, file)
                writepath = os.path.relpath(filepath, parent_path)
                zip_dir.write(filepath, writepath)
        zip_dir.close()


if __name__ == '__main__':
    spider = SpiderNongYaoHeroSkinImg()
    spider.hero_num = 5
    spider.skin_output_path = './images/nongyao/'
    spider.skin_zip_path = './images/nongyao_skin.zip'
    spider.__main__()

